package com.example.controllers;

import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.websocket.server.PathParam;
import javax.ws.rs.Produces;

import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.example.dtos.CartDTO;
import com.example.dtos.CustomerDTO;
import com.example.dtos.ItemToPurchaseDTO;
import com.example.dtos.ProductDTO;
import com.example.dtos.UsersDTO;
import com.example.exceptions.MissingAttributesException;
import com.example.exceptions.WrongFormatException;
import com.example.models.Cart;
import com.example.models.Customer;
import com.example.models.ItemToPurchase;
import com.example.models.Product;
import com.example.services.CartService;
import com.example.validators.HibernateValidator;
import com.wordnik.swagger.annotations.Api;

@RestController
@RequestMapping("/carts")
@Api(value = "/carts", description = "Operations involving carts")
public class CartController {
	@Autowired
	CartService cartService;
	
	@Autowired
	private Mapper mapper;
	
	HibernateValidator<Cart,CartDTO> validator = new HibernateValidator<Cart,CartDTO>();
	
	/*****************************GET*******************************************/
	@RequestMapping(value="/{cartId}", method=RequestMethod.GET)
	@ResponseStatus(value= HttpStatus.OK)
	  public CartDTO getCart(@PathVariable String cartId){
		 return mapper.map(cartService.find(cartId),CartDTO.class);
	 }
	
	@RequestMapping(method = RequestMethod.GET)
	@ResponseStatus(value= HttpStatus.OK)
	  public Collection<CartDTO> allCarts(){
		 Collection<CartDTO> result= new ArrayList<CartDTO>();
		 cartService.findAll().stream().forEach((p)->{result.add(mapper.map(p,CartDTO.class));});
	     return result;
	 }
	
	@RequestMapping(value="/{cartId}/items", method=RequestMethod.GET)
	@ResponseStatus(value= HttpStatus.OK)
	  public Collection<ItemToPurchaseDTO> getCartItems(@PathVariable String cartId){
		List<ItemToPurchaseDTO> result= new ArrayList<ItemToPurchaseDTO>();
		 cartService.itemsOfCart(cartId).stream().forEach((i)->{result.add(mapper.map(i,ItemToPurchaseDTO.class));});
	     Collections.sort(result);
		 return result;
	 }
	
	@RequestMapping(value="/{cartId}/items/{itemId}", method=RequestMethod.GET)
	@ResponseStatus(value= HttpStatus.OK)
	  public ItemToPurchaseDTO getCartItem(@PathVariable String cartId,@PathVariable String itemId){
		ItemToPurchaseDTO res = mapper.map(cartService.itemOfCart(cartId,itemId),ItemToPurchaseDTO.class);
		return res;
	 }
	
	@RequestMapping(value="/{cartId}/customer", method=RequestMethod.GET)
	@ResponseStatus(value= HttpStatus.OK)
	  public CustomerDTO getCartCustomer(@PathVariable String cartId){
		CustomerDTO res = mapper.map(cartService.customerOfCart(cartId),CustomerDTO.class);
		return res;
	 }
	
	/*****************************POST*******************************************/
	@RequestMapping(method = RequestMethod.POST)
	@ResponseStatus(value= HttpStatus.CREATED)
	public void saveCart(@RequestBody CartDTO cartDTO){
			Cart newCart = checkAndCreateCart(cartDTO); 
			cartService.saveCart(newCart);
	}
	
	/*****************************PUT*******************************************/
	@RequestMapping(value = "/{cartId}/checkout", method = RequestMethod.PUT)
	@ResponseStatus(value= HttpStatus.OK)
	public void buySavedCart(@PathVariable String cartId) {
		cartService.buy(cartId);
	}
	
	/*****************************DELETE*******************************************/
	@RequestMapping(method = RequestMethod.DELETE, value="/{cartId}")
	@ResponseStatus(value= HttpStatus.NO_CONTENT)
	public void deleteCart(@PathVariable String cartId){
			 cartService.deleteCart(cartId);
	}
	

	/*****************************AUXILIAR METHOD*******************************************/
	private Cart checkAndCreateCart(CartDTO cartDTO){
		validator.validateObject(cartDTO);
		return mapper.map(cartDTO,Cart.class);
	}
}


